import "../theme/index.scss";
import BpmnViewer from "bpmn-js/lib/Viewer";
import MoveCanvasModule from "diagram-js/lib/navigation/movecanvas";
import { DICT_TYPE } from "@/utils/dict";
import { BpmProcessInstanceStatusEnum } from "@/enums/systemEnum";
import { Button, Modal } from "antd";
import { BasicColumn, BasicTable, useRender, useTable } from "@/components/Table";
import { getDate } from "@/utils/dateUtil";
import Icon from "@/components/Icon";
import { useEffect, useRef, useState } from "react";
import "./ProcessDesigner.less";

interface ViewerPropsType {
	xml: string;
	view: object;
}

let bpmnViewer: BpmnViewer | null = null;
export default function ProcessViewer(props: ViewerPropsType) {
	const processCanvas = useRef();
	// const customDefs = useRef();
	const [defaultZoom, setDefaultZoom] = useState(1); // 默认缩放比例
	// const [isLoading, setIsLoading] = useState(false); // 是否加载中

	let processInstance: any = {}; // 流程实例
	let tasks: any[] = []; // 流程任务

	const [dialogVisible, setDialogVisible] = useState(false); // 弹窗可见性
	const [dialogTitle, setDialogTitle] = useState<string | undefined>(undefined); // 弹窗标题
	// let selectActivityType: string | undefined = undefined; // 选中 Task 的活动编号
	let selectTasks: any[] = []; // 选中的任务数组

	const columns: BasicColumn[] = [
		{
			title: "序号",
			dataIndex: "index",
			render: (_, __, index) => index + 1
		},
		{
			title: "审批人",
			dataIndex: "reviewUser",
			render: (_, record) => record.assigneeUser?.nickname || record.ownerUser?.nickname
		},
		{
			title: "发起人",
			dataIndex: "submitUser",
			render: (_, record) => record.assigneeUser.nickname
		},
		{
			title: "部门",
			dataIndex: "",
			render: (_, record) => record.assigneeUser?.deptName || record.ownerUser?.deptName
		},
		{
			title: "开始时间",
			dataIndex: "createTime",
			render: text => useRender.renderDate(text)
		},
		{
			title: "结束时间",
			dataIndex: "endTime",
			render: text => useRender.renderDate(text)
		},
		{
			title: "审批状态",
			dataIndex: "status",
			render: value => useRender.renderDict(value, DICT_TYPE.BPM_TASK_STATUS)
		},
		{
			title: "审批建议",
			dataIndex: "reason"
		},
		{
			title: "耗时",
			dataIndex: "reason",
			render: value => getDate(value)
		}
	];
	const [registerTable, { setProps }] = useTable({
		dataSource: [],
		columns,
		useSearchForm: false
	});

	/** Function */

	/** Zoom：恢复 */
	const processReZoom = () => {
		setDefaultZoom(1);
		bpmnViewer?.get("canvas").zoom("fit-viewport", "auto");
	};

	/** Zoom：放大 */
	const processZoomIn = () => {
		let zoomStep = 0.1;
		let newZoom = Math.floor(defaultZoom * 100 + zoomStep * 100) / 100;
		if (newZoom > 4) {
			throw new Error("[Process Designer Warn ]: The zoom ratio cannot be greater than 4");
		}
		setDefaultZoom(newZoom);
		bpmnViewer?.get("canvas").zoom(newZoom);
	};

	/** Zoom：缩小 */
	const processZoomOut = () => {
		let zoomStep = 0.1;
		let newZoom = Math.floor(defaultZoom * 100 - zoomStep * 100) / 100;
		if (newZoom < 0.2) {
			throw new Error("[Process Designer Warn ]: The zoom ratio cannot be less than 0.2");
		}
		setDefaultZoom(newZoom);
		bpmnViewer?.get("canvas").zoom(newZoom);
	};

	/** 流程图预览清空 */
	const clearViewer = () => {
		if (processCanvas.current) {
			processCanvas.current.innerHTML = "";
		}
		if (bpmnViewer) {
			bpmnViewer.destroy();
		}
		bpmnViewer = null;
	};

	/** 添加自定义箭头 */
	// TODO 芋艿：自定义箭头不生效，有点奇怪！！！！相关的 marker-end、marker-start 暂时也注释了！！！
	// const addCustomDefs = () => {
	// 	if (!bpmnViewer) {
	// 		return;
	// 	}
	// 	const canvas = bpmnViewer?.get("canvas");
	// 	const svg = canvas?._svg;
	// 	svg.appendChild(customDefs.current);
	// };

	/** 节点选中 */
	const onSelectElement = (element: any) => {
		// 清空原选中
		// selectActivityType = undefined;
		setDialogTitle(undefined);
		if (!element || !processInstance?.id) {
			return;
		}

		// UserTask 的情况
		const activityType = element.type;
		// selectActivityType = activityType;
		if (activityType === "bpmn:UserTask") {
			setDialogTitle(element.businessObject ? element.businessObject.name : undefined);
			selectTasks = tasks.filter((item: any) => item?.taskDefinitionKey === element.id);
			setDialogVisible(true);
		} else if (activityType === "bpmn:EndEvent" || activityType === "bpmn:StartEvent") {
			setDialogTitle("审批信息");
			selectTasks = [
				{
					assigneeUser: processInstance.startUser,
					createTime: processInstance.startTime,
					endTime: processInstance.endTime,
					status: processInstance.status,
					durationInMillis: processInstance.durationInMillis
				}
			];
			setDialogVisible(true);
		}
		setTimeout(() => {
			setProps({
				dataSource: selectTasks,
				//  控制列显隐
				columns:
					activityType === "bpmn:UserTask"
						? columns
						: columns.filter(column => !["reviewUser", "reason"].includes(column.dataIndex as string))
			});
		}, 0);
	};

	/** 初始化 BPMN 视图 */
	const importXML = async (xml: string) => {
		// 清空流程图
		clearViewer();

		// 初始化流程图
		if (xml != null && xml !== "") {
			try {
				bpmnViewer = new BpmnViewer({
					additionalModules: [MoveCanvasModule],
					container: processCanvas.current
				});
				// 增加点击事件
				bpmnViewer.on("element.click", ({ element }) => {
					onSelectElement(element);
				});

				// 初始化 BPMN 视图
				// setIsLoading(true);
				await bpmnViewer.importXML(xml);
				// 自定义成功的箭头
				// addCustomDefs();
			} catch (e) {
				console.log(e);
				// clearViewer();
			} finally {
				// setIsLoading(false);
				// 高亮流程
				setProcessStatus(props.view);
			}
		}
	};

	/** 高亮流程 */
	const setProcessStatus = (view: any) => {
		// 设置相关变量
		if (!view || !view.processInstance) {
			return;
		}
		processInstance = view.processInstance;
		tasks = view.tasks;
		// if (isLoading || !bpmnViewer) {
		if (!bpmnViewer) {
			return;
		}
		const { unfinishedTaskActivityIds, finishedTaskActivityIds, finishedSequenceFlowActivityIds, rejectedTaskActivityIds } = view;
		const canvas = bpmnViewer.get("canvas");
		const elementRegistry = bpmnViewer.get("elementRegistry");

		// 已完成节点
		if (Array.isArray(finishedSequenceFlowActivityIds)) {
			finishedSequenceFlowActivityIds.forEach((item: any) => {
				if (item != null) {
					canvas.addMarker(item, "success");
					const element = elementRegistry.get(item);
					const conditionExpression = element.businessObject.conditionExpression;
					if (conditionExpression) {
						canvas.addMarker(item, "condition-expression");
					}
				}
			});
		}
		if (Array.isArray(finishedTaskActivityIds)) {
			finishedTaskActivityIds.forEach((item: any) => canvas.addMarker(item, "success"));
		}

		// 未完成节点
		if (Array.isArray(unfinishedTaskActivityIds)) {
			unfinishedTaskActivityIds.forEach((item: any) => canvas.addMarker(item, "primary"));
		}

		// 被拒绝节点
		if (Array.isArray(rejectedTaskActivityIds)) {
			rejectedTaskActivityIds.forEach((item: any) => {
				if (item != null) {
					canvas.addMarker(item, "danger");
				}
			});
		}

		// 特殊：处理 end 节点的高亮。因为 end 在拒绝、取消时，被后端计算成了 finishedTaskActivityIds 里
		if ([BpmProcessInstanceStatusEnum.CANCEL, BpmProcessInstanceStatusEnum.REJECT].includes(processInstance.status)) {
			const endNodes = elementRegistry.filter((element: any) => element.type === "bpmn:EndEvent");
			endNodes.forEach((item: any) => {
				canvas.removeMarker(item.id, "success");
				if (processInstance.status === BpmProcessInstanceStatusEnum.CANCEL) {
					canvas.addMarker(item.id, "cancel");
				} else {
					canvas.addMarker(item.id, "danger");
				}
			});
		}
	};

	/** Effect */

	useEffect(() => {
		importXML(props.xml);
	}, [props.xml, props.view]);

	useEffect(() => {
		return () => {
			clearViewer();
		};
	}, []);

	return (
		<div className="process-viewer w-100% h-100%">
			<div style={{ height: "100%" }} ref={processCanvas}></div>
			{/* <!-- 自定义箭头样式，用于已完成状态下流程连线箭头 --> */}
			{/* <defs ref={customDefs}>
				<marker
					id="sequenceflow-end-white-success"
					viewBox="0 0 20 20"
					refX="11"
					refY="10"
					markerWidth="10"
					markerHeight="10"
					orient="auto"
				>
					<path
						className="success-arrow"
						d="M 1 5 L 11 10 L 1 15 Z"
						style={{ strokeWidth: "1px", strokeLinecap: "round", strokeDasharray: "10000, 1" }}
					/>
				</marker>
				<marker
					id="conditional-flow-marker-white-success"
					viewBox="0 0 20 20"
					refX="-1"
					refY="10"
					markerWidth="10"
					markerHeight="10"
					orient="auto"
				>
					<path
						className="success-conditional"
						d="M 0 10 L 8 6 L 16 10 L 8 14 Z"
						style={{ strokeWidth: "1px", strokeLinecap: "round", strokeDasharray: "10000, 1" }}
					/>
				</marker>
			</defs> */}
			{/* <!-- Zoom：放大、缩小 --> */}
			<div className="absolute top-0 right-0">
				<div className="designerPanel">
					<div className="designerPanel-buttonGroup">
						<Button disabled={defaultZoom <= 0.3} icon={<Icon icon="ep:zoom-out" />} onClick={processZoomOut} />
						<Button style={{ width: "90px" }}>{Math.floor(defaultZoom * 10 * 10) + "%"}</Button>
						<Button disabled={defaultZoom >= 3.9} icon={<Icon icon="ep:zoom-in" />} onClick={processZoomIn} />
						<Button icon={<Icon icon="ep:scale-to-original" />} onClick={processReZoom} />
					</div>
				</div>
			</div>
			{/* <!-- 审批记录 --> */}
			<Modal
				title={dialogTitle || "审批记录"}
				open={dialogVisible}
				width="1000px"
				footer={null}
				onCancel={() => setDialogVisible(false)}
			>
				<BasicTable register={registerTable} />
			</Modal>
		</div>
	);
}
